#include "xiaonei_adapter.h"

#include <string>
#include <iostream>

#include "pugixml/pugixml.hpp"

#include "base/curl_client.h"
#include "base/hash.h"
#include "base/logging.h"

namespace sns {
namespace xiaonei {

using namespace std;

const static string kXiaoneiRestUrl = "http://api.xiaonei.com/restserver.do";
const static char * kDemoAppApiKey = "2b33c630b1aa4bfc8068c54b3d0ce44e";
const static char * kDemoAppSecretKey = "7f5416cb3b03476e8c47b4911c98b763";

const static char * kHappyFarmApiKey = "540b23c85c5f474f91b0196a9cfea621";
const static char * kHappyFarmSecretKey = "unknown";

const XiaoneiAdapter & XiaoneiAdapter::demo_app() {
  static XiaoneiAdapter adapter(kDemoAppApiKey, kDemoAppSecretKey);
  return adapter;
}

const XiaoneiAdapter & XiaoneiAdapter::happy_farm() {
  static XiaoneiAdapter adapter(kHappyFarmApiKey, kHappyFarmSecretKey);
  return adapter;
}

// <error_response>
//   <error_code>450</error_code>
//   <error_msg>当前用户session_key已过期</error_msg>
//   <request_args>
//     <arg>
//       <key>method</key>
//       <value>xiaonei.friends.getFriends</value>
//     </arg>
//     <arg>
//       <key>session_key</key>
//       <value>2.55a31f27e7e244070e32d88e377fbb09.3600.1288198800-249539684</value>
//     </arg>
//     <arg>
//       <key>api_key</key>
//       <value>2b33c630b1aa4bfc8068c54b3d0ce44e</value>
//     </arg>
//   </request_args>
// </error_response>
static void DumpErrorMessage(const pugi::xml_node & node) {
  if (node) {
    LOG_INFO("error_code : " << node.child_value("error_code"));
    LOG_INFO("error_msg  : " << node.child_value("error_msg"));
  }
}

// <?xml version="1.0" encoding="UTF-8"?>
// <friends_getFriends_response xmlns="http://api.xiaonei.com/1.0/" 
//   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
//   xsi:schemaLocation="http://api.xiaonei.com/1.0/ http://api.xiaonei.com/1.0/xiaonei.xsd" list="true">
//   <friend>
//     <id>277093904</id>
//     <name><![CDATA[joy3 ]]></name>
//     <headurl>http://head.xiaonei.com/photos/0/0/men_head.gif</headurl>
//     <tinyurl>http://head.xiaonei.com/photos/0/0/men_tiny.gif</tinyurl>
//   </friend>
//   <friend>
//     <id>302516607</id><name>
//       <![CDATA[张菊萍]]></name>
//     <headurl>http://hdn.xnimg.cn/photos/hdn121/20091120/2225/h_head_t3PP_0c730000caa02f76.jpg</headurl>
//     <tinyurl>http://hdn.xnimg.cn/photos/hdn121/20091120/2225/h_tiny_0o9w_0c730000caa02f76.jpg</tinyurl></friend>
//   <friend>
// </friends_getFriends_response>
vector<UserProfile> XiaoneiAdapter::GetFriends(const string & session_key) const {
  map<string, string> post_args;
  post_args.insert(make_pair("api_key", api_key_));
  post_args.insert(make_pair("session_key", session_key));
  post_args.insert(make_pair("method", "xiaonei.friends.getFriends"));

  string xml = CurlGet(post_args);

  pugi::xml_document doc;
  vector<UserProfile> friends;
  if (doc.load(xml.c_str())) {
    const pugi::xml_node & friend_list = doc.child("friends_getFriends_response");
    if (friend_list) {
      UserProfile user;
      for(pugi::xml_node f = friend_list.child("friend"); f; f = f.next_sibling("friend")) {
        LOG_DEBUG(f.child_value("id") << " : " << f.child_value("name"));

        user.id = f.child_value("id");
        user.name = f.child_value("name");
        user.head_url = f.child_value("headurl");
        user.tiny_url = f.child_value("tinyurl");

        friends.push_back(user);
      }
    } else {
      DumpErrorMessage(doc.child("error_response"));
    }
  }

  return friends;
}

// <friends_getAppFriends_response xmlns="http://api.xiaonei.com/1.0/"
//   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
//   xsi:schemaLocation="http://api.xiaonei.com/1.0/ http://api.xiaonei.com/1.0/xiaonei.xsd">
//   <uid>240808027</uid>
//   <uid>272637098</uid>
//   <uid>222974965</uid>
// </friends_getAppFriends_response> 
vector<string> XiaoneiAdapter::GetAppFriends(const string & session_key) const {
  map<string, string> post_args;
  post_args.insert(make_pair("api_key", api_key_));
  post_args.insert(make_pair("session_key", session_key));
  post_args.insert(make_pair("method", "xiaonei.friends.getAppFriends"));

  string xml = CurlGet(post_args);

  pugi::xml_document doc;
  vector<string> friend_ids;
  if (doc.load(xml.c_str())) {
    const pugi::xml_node & uid_list = doc.child("friends_getAppFriends_response");
    if (uid_list) {
      for(pugi::xml_node n = uid_list.child("uid"); n; n = n.next_sibling("uid")) {
        LOG_DEBUG("app friend : " << n.first_child().value());
        friend_ids.push_back(n.first_child().value());
      }
    } else {
      DumpErrorMessage(doc.child("error_response"));
    }
  }

  return friend_ids;
}

// <users_getInfo_response xmlns="http://api.xiaonei.com/1.0/"
//   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
//   xsi:schemaLocation="http://api.xiaonei.com/1.0/ http://api.xiaonei.com/1.0/xiaonei.xsd"
//   list="true">
//   <user>
//     <uid>249539684</uid>
//     <name>李露熙</name>
//     <sex>0</sex>
//     <star>1</star>
//     <zidou>0</zidou>
//     <vip>1</vip>
//     <tinyurl>http://hdn101.xnimg.cn/photos/hdn101/20081230/20/20/tiny_33vv_8078n198107.jpg</tinyurl>
//     <headurl>http://hdn.xnimg.cn/photos/hdn501/20081230/20/20/head_pFa6_7878c198107.jpg</headurl>
//   </user>
//   <user> ... </user>
// </users_getInfo_response>
// UserProfile XiaoneiAdapter::GetUserInfo(const string & session_key) const {
vector<UserProfile> XiaoneiAdapter::GetUserInfo(const string & session_key, const vector<string> & uids) const {
  map<string, string> post_args;
  post_args.insert(make_pair("api_key", api_key_));
  post_args.insert(make_pair("session_key", session_key));
  post_args.insert(make_pair("method", "xiaonei.users.getInfo"));

  string uids_value;
  for(size_t i = 0; i < uids.size(); ++i) {
    if (i > 0) {
      uids_value += ',';
    }
    uids_value += uids[i];
  }
  post_args.insert(make_pair("uids", uids_value));

  string xml = CurlGet(post_args);
  vector<UserProfile> users;
  pugi::xml_document doc;
  if (doc.load(xml.c_str())) {
    const pugi::xml_node & user_node_list = doc.child("users_getInfo_response");
    if (user_node_list) {
      UserProfile user;
      for(pugi::xml_node u = user_node_list.child("user"); u; u = u.next_sibling("user")) {
        LOG_DEBUG(u.child_value("uid") << " : " << u.child_value("name"));
        user.id = u.child_value("uid");
        user.name = u.child_value("name");
        user.head_url = u.child_value("headurl");
        user.tiny_url = u.child_value("tinyurl");

        users.push_back(user);
      }
    } else {
      DumpErrorMessage(doc.child("error_response"));
    }
  }

  return users;
}

string XiaoneiAdapter::CurlGet(const map<string, string> & post_args) const {
  string md5_source, post_body;
  map<string, string>::const_iterator it = post_args.begin();
  for(; it != post_args.end(); ++it) {
    md5_source += it->first;
    md5_source += '=';
    md5_source += it->second;
    if (!post_body.empty()) {
      post_body += '&';
    }
    post_body += it->first;
    post_body += '=';
    post_body += it->second;
  }
  md5_source += secret_key_;
  if (!post_body.empty()) {
    post_body += "&sig=";
    post_body += base::HashMD5(md5_source.c_str(), md5_source.size());
  }

  string xml;
  int res = base::CurlClient::Instance().Post(kXiaoneiRestUrl, post_body, &xml);
  if (res != 0) {
    LOG_WARN("xiaonei CurlClient::Post() error : " << res);
  }
  // LOG_DEBUG(xml);
  return xml;
}

}
}
